use std::{io::Cursor, str::FromStr};

use bytes::Buf;
use serde::{Deserialize, Serialize};
use serde_json::Error;

// 聊天
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Chat {
    pub chat_type: ChatType,
    pub no: String,
}

impl Chat {
    pub(crate) fn new(chat_type: ChatType, no: String) -> Self {
        Self { chat_type, no }
    }
}

// 添加群聊或者好友
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Add {
    pub add_type: AddType,
    pub no: String,
}

impl Add {
    pub(crate) fn new(add_type: AddType, no: String) -> Self {
        Self { add_type, no }
    }
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum OperationType {
    Chat,           //@
    MakeMeet,       //#
    UpdateName,     //%
    JoinMeet,       //^
    ExitMeet,       //&
    AddRequest,     //(
    AddAnswer,      //)
    RemoveFriend,   //*
    FriendList,     //~-
    MeetList,       //~+
    AddRequestList, //~(
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Opration {
    pub operation_type: OperationType,
    pub chat: Option<Chat>,
    pub add: Option<Add>,
    pub message: String,
}

impl Opration {
    pub(crate) fn new(operation_type: OperationType) -> Self {
        Self {
            operation_type,
            chat: None,
            add: None,
            message: "".to_string(),
        }
    }

    pub(crate) fn with_chat(
        operation_type: OperationType,
        chat: Option<Chat>,
        message: String,
    ) -> Self {
        Self {
            operation_type,
            chat,
            add: None,
            message,
        }
    }

    pub(crate) fn with_add(
        operation_type: OperationType,
        add: Option<Add>,
        message: String,
    ) -> Self {
        Self {
            operation_type,
            chat: None,
            add,
            message,
        }
    }

    pub fn parse_from_str(s: &str) -> Self {
        Self::from_str(s).unwrap()
    }
}

impl FromStr for Opration {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        serde_json::from_str(s)
    }
}

// 聊天方式
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum ChatType {
    //私聊
    Person,
    //群聊
    Meet,
}

// 添加方式
#[derive(Debug, Serialize, Deserialize, Clone)]
pub enum AddType {
    //私聊
    Person,
    //群聊
    Meet,
}

pub(crate) fn parse(src: &mut Cursor<&[u8]>) -> Option<Opration> {
    if src.has_remaining() {
        return match src.get_u8() {
            b'@' => match src.get_u8() {
                b'-' => {
                    let chat = Chat::new(
                        ChatType::Person,
                        match get_no(src) {
                            Some(no) => no,
                            None => {
                                return None;
                            }
                        },
                    );
                    Some(Opration::with_chat(
                        OperationType::Chat,
                        Some(chat),
                        get_msg(src).unwrap(),
                    ))
                }
                b'+' => {
                    let chat = Chat::new(
                        ChatType::Meet,
                        match get_no(src) {
                            Some(no) => no,
                            None => {
                                return None;
                            }
                        },
                    );
                    Some(Opration::with_chat(
                        OperationType::Chat,
                        Some(chat),
                        match get_msg(src) {
                            Some(msg) => msg,
                            None => {
                                return None;
                            }
                        },
                    ))
                }
                _ => {
                    log::error!("");
                    None
                }
            },
            b'#' => {
                log::info!("make meet");
                None
            }
            b'$' => {
                log::info!("update user name");
                None
            }
            b'%' => {
                log::info!("update meet name");
                None
            }
            b'^' => {
                log::info!("join meet");
                None
            }
            b'&' => {
                log::info!("exit meet");
                None
            }
            //添加好友
            b'(' => match src.get_u8() {
                b'-' => {
                    let add = Add::new(
                        AddType::Person,
                        match get_no(src) {
                            Some(no) => no,
                            None => {
                                return None;
                            }
                        },
                    );
                    Some(Opration::with_add(
                        OperationType::AddRequest,
                        Some(add),
                        get_msg(src).unwrap(),
                    ))
                }
                b'+' => {
                    let add = Add::new(
                        AddType::Meet,
                        match get_no(src) {
                            Some(no) => no,
                            None => {
                                return None;
                            }
                        },
                    );
                    Some(Opration::with_add(
                        OperationType::AddRequest,
                        Some(add),
                        match get_msg(src) {
                            Some(msg) => msg,
                            None => {
                                return None;
                            }
                        },
                    ))
                }
                _ => {
                    log::error!("");
                    None
                }
            },
            //添加好友
            b')' => match src.get_u8() {
                b'-' => {
                    let add = Add::new(
                        AddType::Person,
                        match get_no(src) {
                            Some(no) => no,
                            None => {
                                return None;
                            }
                        },
                    );
                    Some(Opration::with_add(
                        OperationType::AddAnswer,
                        Some(add),
                        get_msg(src).unwrap(),
                    ))
                }
                b'+' => {
                    let add = Add::new(
                        AddType::Meet,
                        match get_no(src) {
                            Some(no) => no,
                            None => {
                                return None;
                            }
                        },
                    );
                    Some(Opration::with_add(
                        OperationType::AddAnswer,
                        Some(add),
                        match get_msg(src) {
                            Some(msg) => msg,
                            None => {
                                return None;
                            }
                        },
                    ))
                }
                _ => {
                    log::error!("");
                    None
                }
            },
            b'*' => {
                log::info!("remove friend");
                None
            }
            b'~' => match src.get_u8() {
                b'-' => Some(Opration::new(OperationType::FriendList)),
                b'+' => Some(Opration::new(OperationType::MeetList)),
                b'(' => Some(Opration::new(OperationType::AddRequestList)),
                _ => None,
            },
            _ => {
                log::error!("");
                None
            }
        };
    }
    None
}
fn get_no(src: &mut Cursor<&[u8]>) -> Option<String> {
    let start = src.position() as usize;
    let end = src.get_ref().len() - 1;
    for i in start..end {
        if src.get_ref()[i] == b':' && src.get_ref()[i + 1] == b':' {
            src.set_position((i + 2) as u64);
            let no = &src.get_ref()[start..i];
            return Some(String::from_utf8(no.to_vec()).unwrap());
        }
    }
    None
}

fn get_msg(src: &Cursor<&[u8]>) -> Option<String> {
    let start = src.position() as usize;
    let end = src.get_ref().len();
    let msg = &src.get_ref()[start..end];
    Some(String::from_utf8(msg.to_vec()).unwrap())
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Message {
    msg_type: MsgType,
    no: Option<String>,
    context: String,
}

impl FromStr for Message {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        serde_json::from_str(s)
    }
}

impl Message {
    pub(crate) fn system_msg(context: String) -> Self {
        Self {
            msg_type: MsgType::System,
            no: None,
            context,
        }
    }
    pub(crate) fn person_msg(no: String, context: String) -> Self {
        Self {
            msg_type: MsgType::Person,
            no: Some(no),
            context,
        }
    }
    pub fn parse_from_str(s: &str) -> Self {
        Self::from_str(s).unwrap()
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum MsgType {
    System,
    Person,
    Meet,
}

#[test]
fn cursor_test() {
    let data = [0_u8; 10];
    let cursor = Cursor::new(&data[..]);

    let start = 2;
    let end = 6;

    // 从 Cursor 中获取指定范围的数据切片
    let slice = &cursor.get_ref()[start..end];

    println!("Data slice: {:?}", slice);
}
